/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package fork.modbox;

import fork.Modbox;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import tal.drivechain.chain.Chain;
import tal.drivechain.gui.ForkScrollBarUI;
import tal.drivechain.gui.GUIPopup;
import tal.drivechain.gui.GUITextBox;
import tal.drivechain.gui.TextButton;
import tal.drivechain.module.properties.ColorParser;
import tal.drivechain.variable.VarTableListener;
import tal.drivechain.variable.Variable;

/**
 *
 * @author Tal Eisenberg
 */

/*
 notes:
 nameField in VarItem should look like mod instance name in the node popup
 valueField should stop updating its value if it has focus.

 */
public class VariablePopup extends GUIPopup implements VarTableListener {
    private Modbox owner;

    private JTextField varField = new JTextField(20);
    private TextButton addButton;
    private JScrollPane scroll;
    private VariableList varList;
    private JPanel blackPanel;
    private Chain chain;
    private Font courier;
    
    public VariablePopup(Modbox owner) {
        super(ColorParser.xor(owner.getColor()));
        this.owner = owner;
        this.setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0; c.gridy = 0; c.weightx = 1; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.FIRST_LINE_START;
        varField.setToolTipText("Enter a variable definition in the format of name(type:value) or name(value).");
        varField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent ke) {
                if (ke.getKeyCode()==KeyEvent.VK_ENTER)
                    addVariable();
            }
        });
        this.add(varField, c);

        c.gridx = 1; c.weightx = 0; c.anchor = GridBagConstraints.FIRST_LINE_END;
        addButton = new TextButton("add", ColorParser.xor(owner.getColor()), owner.getFont());
        addButton.setNegative(false);
        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                addVariable();
            }
        });
        this.add(addButton, c);

        varList = new VariableList();
        scroll = new JScrollPane();
        blackPanel = new JPanel();
        blackPanel.setBackground(Color.BLACK);
        scroll.setCorner(JScrollPane.LOWER_TRAILING_CORNER, blackPanel);
        scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scroll.setViewportView(varList);
        c.gridheight = 1; c.gridx = 0; c.gridy = 1; c.weighty = 1; c.weightx = 1;
        c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST;
        c.insets.right = 0; c.insets.top = 0; c.insets.bottom = 0; c.insets.left = 0;
        this.add(scroll, c);

        pack();
    }

    private void addVariable() {
        owner.sendShellCommand("make var " + varField.getText());
        new Thread() {
            @Override
            public void run() {
                varField.setBorder(BorderFactory.createLineBorder(owner.getColor()));
                try {
                    sleep(300);
                } catch (InterruptedException ex) {
                    Logger.getLogger(VariablePopup.class.getName()).log(Level.SEVERE, null, ex);
                }
                varField.setBorder(BorderFactory.createLineBorder(ColorParser.xor(owner.getColor())));
            }
        }.start();
    }

    public void setChain(Chain c) {
        if (c==chain) return;
        if (chain!=null) chain.getVarTable().removeListener(this);
        this.chain = c;
        if (c!=null) {
            c.getVarTable().addListener(this);
            varList.updateList();
        }
    }

    @Override
    public void setColor(Color c) {
        Color xor = ColorParser.xor(c);
        super.setColor(xor);
        varField.setForeground(xor);
        varField.setBackground(Color.black);
        varField.setCaretColor(xor.brighter());
        varField.setSelectionColor(xor.darker());
        varField.setBorder(BorderFactory.createLineBorder(xor));

        addButton.setColor(ColorParser.lighter(xor));

        if (scroll != null) {
            scroll.setBackground(Color.BLACK);
            scroll.getHorizontalScrollBar().setUI(new ForkScrollBarUI(xor, xor.darker()));
            scroll.getVerticalScrollBar().setUI(new ForkScrollBarUI(xor, xor.darker()));
        }


        varList.setColor(c);

    }

    @Override
    public void setFont(Font f) {
//        System.out.println("setFont to " + f.getName() + ":" + f.getSize());
        courier = new Font("courier", Font.BOLD, (int)(f.getSize()));
        addButton.setFont(f);
        varField.setFont(courier);
        varList.setFont(courier);
    }

    public void globalMessageEvent(Variable message) {
    }

    public void setVarEvent(Variable message) {
        if (!varList.varItems.containsKey(message.getName()))
            varList.updateList();
        else varList.varItems.get(message.getName()).setVarValue(message.getValueDefinition(chain));

    }

    public void removeVarEvent(Variable var) {
        varList.updateList();
    }

    public void varScopeChanged(Variable var, boolean isPublic) {
//        System.out.println("variable popup: varScopeChanged");
        varList.updateList();
    }

    class VariableList extends JPanel {
        HashMap<String, VarItem> varItems;

        public VariableList() {
            varItems = new HashMap<String, VarItem>();
            this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            this.setBackground(Color.black);
        }

        public void setColor(Color c) {
            if (varItems!=null && !varItems.isEmpty())
                for (VarItem i : varItems.values()) i.setColor(c);
        }

        @Override
        public void setFont(Font f) {
            if (varItems!=null && !varItems.isEmpty())
                for (VarItem i : varItems.values()) i.setFont(f);
        }

        private void updateList() {
            varItems.clear();
            removeAll();
            if (VariablePopup.this.chain.getVarTable().isEmpty()) {
                VariablePopup.this.scroll.setVisible(false);
            } else {
                for (String name : VariablePopup.this.chain.getVarTable().keySet()) {
                    VarItem item = new VarItem(name);
                    varItems.put(name, item);
                    item.setVarValue(VariablePopup.this.chain.getVarTable().get(name).getValueDefinition(chain));
                    item.setPublic(VariablePopup.this.chain.getVarTable().isPublicVar(name));
                    add(item);
                }
                VariablePopup.this.scroll.setVisible(true);
            }
            setColor(owner.getColor());
            setFont(courier);
            this.validateTree();
            this.repaint();

            VariablePopup.this.pack();
        }

        class VarItem extends JPanel {
            TextButton publicButton;
            GUITextBox nameText, valueText;
            TextButton removeButton;
            String varName;

            public VarItem(String varName) {
                this.varName = varName;
                setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
                publicButton = new TextButton("P", VariablePopup.this.owner.getColor(), VariablePopup.this.owner.getFont());
                publicButton.setNegative(false);
                publicButton.setToggleButton(true);
                publicButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent ae) {
                        VariablePopup.this.chain.getVarTable().setPublicVar(VarItem.this.varName, publicButton.isSelected());
                    }
                });

                nameText = new GUITextBox();
                nameText.setColumns(10);
                nameText.initTextComponent();
                nameText.setText(varName);
                nameText.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
                nameText.getTextComponent().setBorder(BorderFactory.createEmptyBorder());

                valueText = new GUITextBox();
                valueText.setColumns(30);
                valueText.initTextComponent();
                valueText.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
                
                removeButton = new TextButton("x", VariablePopup.this.owner.getColor(), VariablePopup.this.owner.getFont());
                removeButton.setNegative(true);
                removeButton.setHasBorder(false);
                removeButton.setToolTipText("Remove variable.");
                removeButton.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent ae) {
                        owner.sendShellCommand("remove var " + VarItem.this.varName);
                    }
                });

                add(publicButton);
                add(nameText);
                add(valueText);
                add(removeButton);
            }

            public void setColor(Color c) {
                Color xor = ColorParser.xor(c);
                publicButton.setColor(ColorParser.lighter(xor));
                nameText.setColor(ColorParser.lighter(xor));
                nameText.setNegative(true);
                valueText.setColor(ColorParser.lighter(xor));
                valueText.setNegative(false);
                removeButton.setColor(ColorParser.lighter(xor));
            }

            @Override
            public Dimension getPreferredSize() {
                int w = publicButton.getPreferredSize().width + nameText.getPreferredSize().width +
                        valueText.getPreferredSize().width + removeButton.getPreferredSize().width;
                int h = Math.max(publicButton.getPreferredSize().height,
                            Math.max(nameText.getPreferredSize().height,
                            Math.max(valueText.getPreferredSize().height, removeButton.getPreferredSize().height)));
                return new Dimension(w,h);
            }

            @Override
            public void setFont(Font f) {
                if (publicButton!=null) {
                    publicButton.setFont(f);
                    nameText.setFont(f);
                    valueText.setFont(f);
                    removeButton.setFont(f);
                }
            }

            public void setVarName(String name) {
                nameText.setText(name);
            }

            public void setVarValue(String value) {
                valueText.setText(value);
            }

            private void setPublic(boolean publicVar) {
                publicButton.setSelected(publicVar);
                if (publicButton.isSelected()) publicButton.setToolTipText("Public variable.");
                else publicButton.setToolTipText("Private variable.");
            }
        }
    }
}

